home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / 3dvect37.zip / XSCALE.INC < prev   
Text File  |  1994-06-22  |  39KB  |  872 lines

  1. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2. ;
  3. ; Filename     : xscale.inc
  4. ; Included from: 3D1.ASM, 3D2.ASM, 3D3.ASM
  5. ; Description  : Bitmap Scaling routines - non-cartisian plotting
  6. ;
  7. ; XSCALE1.ASM by John A. Slagel, jas37876@uxa.cso.uiuc.edu
  8. ; This is some code to do bitmap scaling in VGA Mode X.  It can scale a
  9. ; bitmap of any size down to 2 pixels wide, or up to thousands of pixels
  10. ; wide.  It performs complete clipping, with only a small constant amount
  11. ; of time to clip, no matter how huge the image is.  It draws column by
  12. ; column to reduce the number of plane switches, which are slow. The inner
  13. ; column loop has been optimized for no memory accesses, except to read or
  14. ; write a pixel.  This uses MASM 5.1 features, and can be compiled in any
  15. ; memory model by changing the .MODEL line, but make sure that you always
  16. ; pass a far pointer to the bitmap data, regardless of memory model.
  17. ; C-callable as:
  18. ;   void XSCALE1( int X, int Y, int DW, int DY,
  19. ;                     int SW, int SH, void far * Bitmap );
  20. ; X,Y   are the upper left-hand coordinates of where to draw the bitmap.
  21. ; DW,DH are the width and height of the SCALEed bitmap
  22. ; SW,SH are the width and height of the source bitmap.
  23. ; Bitmap is a pointer to the bitmap bits.
  24. ;
  25. ; Routine has been modified for 32 bit protected mode by John McCarthy.
  26. ; John McCarthy thanks John A. Slagel for providing this code, and hopes
  27. ; John A. Slagel is not offended by the changes.
  28. ;
  29. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  30.  
  31.             public draw_scale
  32.             public tdraw_scale
  33.             public tdraw_scale4
  34.             public xscale1
  35.             public xscale2
  36.             public xscale4
  37.             public repeat_bitmap
  38.  
  39. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  40. ;
  41. ; Draw_Scale - draw scaled bitmap in modex
  42. ; In:
  43. ;    ESI - offset of bitmap to draw, first two words are x,y size
  44. ;     AX - x width to scale to
  45. ;     BX - y width to scale to
  46. ;     CX - x location, non-cartisian
  47. ;     DX - y location, non-cartisian
  48. ; current_page - current offset of video memory for page of xmode, see xmode.asm
  49. ;
  50. ; Out:
  51. ;    null
  52. ;
  53. ; Notes:
  54. ;  destructive bitmap - non-cartisian
  55. ;
  56. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  57.  
  58. draw_scale:
  59.         mov bitmap,esi
  60.         mov destwidth,ax
  61.         mov destheight,bx
  62.         mov destx,cx
  63.         mov desty,dx
  64.  
  65. xscale1:
  66.         cmp     destwidth, 2        ; if destination width is less than 2
  67.         jl      done                ;     then don't draw it.
  68.  
  69.         cmp     destheight, 2       ; if destination height is less than 2
  70.         jl      done                ;     then don't draw it.
  71.  
  72.         mov     ax, desty           ; if it is completely below the
  73.         cmp     ax, clipbt          ; lower clip bondry,
  74.         jg      done                ;     then don't draw it.
  75.  
  76.         add     ax, destheight      ; if it is above clip boundries
  77.         dec     ax                  ;     then don't draw it.
  78.         cmp     ax, cliptp
  79.         jl      done
  80.  
  81.         mov     ax, destx           ; if it is to the right of the
  82.         mov     cx, cliprt          ; right clip boundry
  83.         cmp     ax, cliprt          ;     then don't draw it.
  84.         jg      done
  85.  
  86.         add     ax, destwidth       ; if it is completely to the left
  87.         dec     ax                  ; of the left clip boundry,
  88.         cmp     ax, cliplt          ;     then don't draw it.
  89.         jl      done
  90.  
  91.         mov     esi, bitmap         ; make esi point to bitmap data
  92.         lodsw                       ; get source x width
  93.         mov     sourcewidth,ax
  94.         lodsw                       ; get source y height
  95.         mov     sourceheight,ax
  96.  
  97.         mov     ax, destwidth       ; clippedwidth is initially set to
  98.         mov     clippedwidth, ax    ; the requested dest width.
  99.  
  100.         add     ax,ax               ; initialize the x decision var
  101.         neg     ax                  ; to be -2*destwidth
  102.         mov     decisionx, ax       ;
  103.  
  104.         mov     ax, destheight      ; clippedheight is initially set to
  105.         mov     clippedheight, ax   ; the requested dest size.
  106.  
  107.         add     ax,ax               ; initialize the y decision var
  108.         neg     ax                  ; to be -2*destheight
  109.         mov     decisiony, ax       ;
  110.  
  111.         movsx   eax, cliptp         ; if y is below the top
  112.         mov     edx, eax            ; clipping boundry, then we don't
  113.         sub     dx, desty           ; need to clip the top, so we can
  114.         js      s notopclip         ; jump over the clipping stuff.
  115.  
  116.         mov     desty, ax           ; this block performs clipping on the
  117.         sub     clippedheight, dx   ; top of the bitmap.  i have heavily
  118.         movsx   ecx, sourceheight   ; optimized this block to use only 4
  119.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  120.         mov     eax, ecx            ; gonna try to explain what it's doing.
  121.         cdq                         ; but i can tell you what results from
  122.         movsx   ebx, destheight     ; this:  the decisiony var is updated
  123.         idiv    ebx                 ; to start at the right clipped row.
  124.         movsx   edx, sourcewidth    ; y is moved to the top clip
  125.         imul    edx, eax            ; boundry. clippedheight is lowered since
  126.         add     esi, edx            ; we won't be drawing all the requested
  127.         imul    eax, ebx            ; rows. esi is changed to point over
  128.         sub     ecx, eax            ; the bitmap data that is clipped off.
  129.         sub     ecx, ebx            ;
  130.         add     ecx, ecx            ;
  131.         mov     decisiony, cx       ; <end of top clipping block >
  132.  
  133. notopclip:
  134.         mov     ax, desty           ; if the bitmap doesn't extend over the
  135.         add     ax, clippedheight   ; bottom clipping boundry, then we
  136.         dec     ax                  ; don't need to clip the bottom, so we
  137.         cmp     ax, clipbt          ; can jump over the bottom clip code.
  138.         jle     s nobottomclip      ;
  139.  
  140.         mov     ax, clipbt          ; clip off the bottom by reducing the
  141.         sub     ax, desty           ; clippedheight so that the bitmap won't
  142.         inc     ax                  ; extend over the lower clipping
  143.         mov     clippedheight, ax   ; boundry.
  144.  
  145. nobottomclip:
  146.         movsx   eax, cliplt         ; if x is to the left of the
  147.         mov     edx, eax            ; top clipping boundry, then we don't
  148.         sub     dx, destx           ; need to clip the left, so we can
  149.         js      s noleftclip        ; jump over the clipping stuff.
  150.  
  151.         mov     destx, ax           ; this block performs clipping on the
  152.         sub     clippedwidth, dx    ; left of the bitmap.  i have heavily
  153.         movsx   ecx, sourcewidth    ; optimized this block to use only 4
  154.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  155.         mov     eax, ecx            ; gonna try to explain what it's doing.
  156.         cdq                         ; but i can tell you what results from
  157.         movsx   ebx, destwidth      ; this:  the decisionx var is updated
  158.         idiv    ebx                 ; to start at the right clipped column.
  159.         add     esi, eax            ; x is moved to the left clip
  160.         imul    eax, ebx            ; boundry. clippedwidth is reduced since
  161.         sub     ecx, eax            ; we won't be drawing all the requested
  162.         sub     ecx, ebx            ; cols. esi is changed to point over
  163.         add     ecx, ecx            ; the bitmap data that is clipped off.
  164.         mov     decisionx, cx       ; <end of left clipping block >
  165.  
  166. noleftclip:
  167.         mov     ax, destx           ; if the bitmap doesn't extend over the
  168.         add     ax, clippedwidth    ; right clipping boundry, then we
  169.         dec     ax                  ; don't need to clip the right, so we
  170.         cmp     ax, cliprt          ; can jump over the right clip code.
  171.         jle     s noclipright       ;
  172.  
  173.         mov     ax, cliprt          ; clip off the right by reducing the
  174.         sub     ax, destx           ; clippedwidth so that the bitmap won't
  175.         inc     ax                  ; extend over the right clipping
  176.         mov     clippedwidth, ax    ; boundry.
  177.  
  178.         ;calculate starting video address
  179. noclipright:
  180.         xor     edi,edi
  181.         mov     di, desty           ; we are going to set edi to start point
  182.         imul    edi, xactual/4
  183.         xor     eax,eax
  184.         mov     ax, destx           ; the offset edi is
  185.         mov     cx, ax              ; calculated by:
  186.         shr     ax, 2               ;     di = y*80+x/2
  187.         add     eax, current_page
  188.         add     edi,eax             ; edi is ready!
  189.  
  190.         mov     dx, sc_index        ; point the vga sequencer to the map
  191.         mov     al, map_mask        ; mask register, so that we only need
  192.         out     dx, al              ; to send out 1 byte per column.
  193.  
  194.         inc     dx                  ; move to the sequencer's data register.
  195.         and     cx, 3               ; calculate the starting plane. this is
  196.         mov     al, 11h             ; just:
  197.         shl     al, cl              ; plane =  (11h << (x and 3))
  198.         out     dx, al              ; select the first plane.
  199.  
  200.         xor     ecx,ecx
  201.         mov     cx, sourcewidth     ; use cx for source width
  202.         mov     xad, ecx
  203.         shl     sourcewidth,1
  204.  
  205.         align   16                  ; since this point gets jumped to a lot,
  206.                                     ; make sure that it is dword aligned.
  207. rowloop:
  208.         push    esi                 ; save the starting source index
  209.         push    edi                 ; save the starting dest index
  210.         push    ax                  ; save the current plane mask
  211.         push    bp                  ; save the current base pointer
  212.  
  213.         mov     cx, clippedheight   ; use al for row counter (0-239)
  214.         mov     bx, decisiony       ; use bx for decision variable
  215.         mov     dx, sourceheight    ; use dx for source height * 2
  216.         add     dx, dx
  217.         mov     bp, destheight      ; use bp for dest height * 2
  218.         add     bp, bp
  219.         mov     ah, [esi]           ; get the first source pixel
  220.  
  221.         align   4                   ; common jump point... align for speed.
  222. columnloop:
  223.         mov     [edi], ah           ; draw a pixel
  224.         dec     cx                  ; decrement line counter
  225.         jz      s donewithcol       ; see if we're done with this column
  226.         add     edi, xactual/4      ; go on to the next screen row
  227.         add     bx, dx              ; increment the decision variable
  228.         js      s columnloop        ; draw this source pixel again
  229.  
  230. incsourcerow:
  231.         add     esi, xad            ; move to the next source pixel
  232.         sub     bx, bp              ; decrement the decision variable
  233.         jns     s incsourcerow      ; see if we need to skip another source pixel
  234.         mov     ah, [esi]           ; get the next source pixel
  235.         jmp     s columnloop        ; start drawing this pixel
  236.  
  237. donewithcol:
  238.         pop     bp                  ; restore bp to access variables
  239.         pop     ax                  ; restore al = plane mask
  240.         pop     edi                 ; restore di to top row of screen
  241.         pop     esi                 ; restore si to top row of source bits
  242.  
  243.         rol     al, 1               ; move to next plane
  244.         adc     edi, 0              ; go on to next screen column
  245.         mov     dx, sc_data         ; tell the vga what column we're in
  246.         out     dx, al              ; by updating the map mask register
  247.  
  248.         mov     bx, decisionx       ; use bx for the x decision variable
  249.         add     bx, sourcewidth     ; increment the x decision variable
  250.         js      s nextcol           ; jump if we're still in the same source col.
  251.         mov     dx, destwidth       ; dx = w * 2
  252.         add     dx, dx
  253. incsourcecol:
  254.         inc     esi                 ; move to next source column
  255.         sub     bx, dx              ; decrement x decision variable
  256.         jns     s incsourcecol      ; see if we skip another source column
  257. nextcol:
  258.         mov     decisionx, bx       ; free up bx for colloop
  259.         dec     clippedwidth        ; if we're not at last column
  260.         jnz     rowloop             ;    then do another column
  261. done:
  262.         ret                         ; we're done!
  263.  
  264. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  265. ;
  266. ; TDraw_Scale - Draw transparent scaled bitmap in modex
  267. ; In:
  268. ;    ESI - offset of bitmap to draw, first two words are x,y size
  269. ;     AX - x width to scale to
  270. ;     BX - y width to scale to
  271. ;     CX - x location, non-cartisian
  272. ;     DX - y location, non-cartisian
  273. ; current_page - current offset of video memory for page of xmode, see xmode.asm
  274. ;
  275. ; Out:
  276. ;    null
  277. ;
  278. ; Notes:
  279. ;  transparent bitmap.  any bytes that = 0 are skipped,- non-cartisian
  280. ;
  281. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  282.  
  283. tdraw_scale:
  284.         mov bitmap,esi
  285.         mov destwidth,ax
  286.         mov destheight,bx
  287.         mov destx,cx
  288.         mov desty,dx
  289.  
  290. xscale2:
  291.         cmp     destwidth, 2        ; if destination width is less than 2
  292.         jl      s done              ;     then don't draw it.
  293.  
  294.         cmp     destheight, 2       ; if destination height is less than 2
  295.         jl      s done              ;     then don't draw it.
  296.  
  297.         mov     ax, desty           ; if it is completely below the
  298.         cmp     ax, clipbt          ; lower clip bondry,
  299.         jg      s done              ;     then don't draw it.
  300.  
  301.         add     ax, destheight      ; if it is above clip boundries
  302.         dec     ax                  ;     then don't draw it.
  303.         cmp     ax, cliptp
  304.         jl      s done
  305.  
  306.         mov     ax, destx           ; if it is to the right of the
  307.         mov     cx, cliprt          ; right clip boundry
  308.         cmp     ax, cliprt          ;     then don't draw it.
  309.         jg      s done
  310.  
  311.         add     ax, destwidth       ; if it is completely to the left
  312.         dec     ax                  ; of the left clip boundry,
  313.         cmp     ax, cliplt          ;     then don't draw it.
  314.         jl      s done
  315.  
  316.         mov     esi, bitmap         ; make esi point to bitmap data
  317.         lodsw                       ; get source x width
  318.         mov     sourcewidth,ax
  319.         lodsw                       ; get source y height
  320.         mov     sourceheight,ax
  321.  
  322.         mov     ax, destwidth       ; clippedwidth is initially set to
  323.         mov     clippedwidth, ax    ; the requested dest width.
  324.  
  325.         add     ax,ax               ; initialize the x decision var
  326.         neg     ax                  ; to be -2*destwidth
  327.         mov     decisionx, ax       ;
  328.  
  329.         mov     ax, destheight      ; clippedheight is initially set to
  330.         mov     clippedheight, ax   ; the requested dest size.
  331.  
  332.         add     ax,ax               ; initialize the y decision var
  333.         neg     ax                  ; to be -2*destheight
  334.         mov     decisiony, ax       ;
  335.  
  336.         movsx   eax, cliptp         ; if y is below the top
  337.         mov     edx, eax            ; clipping boundry, then we don't
  338.         sub     dx, desty           ; need to clip the top, so we can
  339.         js      s notopclip2        ; jump over the clipping stuff.
  340.  
  341.         mov     desty, ax           ; this block performs clipping on the
  342.         sub     clippedheight, dx   ; top of the bitmap.  i have heavily
  343.         movsx   ecx, sourceheight   ; optimized this block to use only 4
  344.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  345.         mov     eax, ecx            ; gonna try to explain what it's doing.
  346.         cdq                         ; but i can tell you what results from
  347.         movsx   ebx, destheight     ; this:  the decisiony var is updated
  348.         idiv    ebx                 ; to start at the right clipped row.
  349.         movsx   edx, sourcewidth    ; y is moved to the top clip
  350.         imul    edx, eax            ; boundry. clippedheight is lowered since
  351.         add     esi, edx            ; we won't be drawing all the requested
  352.         imul    eax, ebx            ; rows. esi is changed to point over
  353.         sub     ecx, eax            ; the bitmap data that is clipped off.
  354.         sub     ecx, ebx            ;
  355.         add     ecx, ecx            ;
  356.         mov     decisiony, cx       ; <end of top clipping block >
  357.  
  358. notopclip2:
  359.         mov     ax, desty           ; if the bitmap doesn't extend over the
  360.         add     ax, clippedheight   ; bottom clipping boundry, then we
  361.         dec     ax                  ; don't need to clip the bottom, so we
  362.         cmp     ax, clipbt          ; can jump over the bottom clip code.
  363.         jle     s nobottomclip2
  364.  
  365.         mov     ax, clipbt          ; clip off the bottom by reducing the
  366.         sub     ax, desty           ; clippedheight so that the bitmap won't
  367.         inc     ax                  ; extend over the lower clipping
  368.         mov     clippedheight, ax   ; boundry.
  369.  
  370. nobottomclip2:
  371.         movsx   eax, cliplt         ; if x is to the left of the
  372.         mov     edx, eax            ; top clipping boundry, then we don't
  373.         sub     dx, destx           ; need to clip the left, so we can
  374.         js      s noleftclip2       ; jump over the clipping stuff.
  375.  
  376.         mov     destx, ax           ; this block performs clipping on the
  377.         sub     clippedwidth, dx    ; left of the bitmap.  i have heavily
  378.         movsx   ecx, sourcewidth    ; optimized this block to use only 4
  379.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  380.         mov     eax, ecx            ; gonna try to explain what it's doing.
  381.         cdq                         ; but i can tell you what results from
  382.         movsx   ebx, destwidth      ; this:  the decisionx var is updated
  383.         idiv    ebx                 ; to start at the right clipped column.
  384.         add     esi, eax            ; x is moved to the left clip
  385.         imul    eax, ebx            ; boundry. clippedwidth is reduced since
  386.         sub     ecx, eax            ; we won't be drawing all the requested
  387.         sub     ecx, ebx            ; cols. esi is changed to point over
  388.         add     ecx, ecx            ; the bitmap data that is clipped off.
  389.         mov     decisionx, cx       ; <end of left clipping block >
  390.  
  391. noleftclip2:
  392.         mov     ax, destx           ; if the bitmap doesn't extend over the
  393.         add     ax, clippedwidth    ; right clipping boundry, then we
  394.         dec     ax                  ; don't need to clip the right, so we
  395.         cmp     ax, cliprt          ; can jump over the right clip code.
  396.         jle     s noclipright2
  397.  
  398.         mov     ax, cliprt          ; clip off the right by reducing the
  399.         sub     ax, destx           ; clippedwidth so that the bitmap won't
  400.         inc     ax                  ; extend over the right clipping
  401.         mov     clippedwidth, ax    ; boundry.
  402.  
  403.         ;calculate starting video address
  404. noclipright2:
  405.         movsx   edi, desty          ; we are going to set edi to start point
  406.         imul    edi, xactual/4
  407.         movsx   eax, destx          ; the offset edi is
  408.         mov     cx, ax              ; calculated by:
  409.         shr     eax, 2              ; edi = y*80+x/2
  410.         add     eax, current_page
  411.         add     edi,eax             ; edi is ready!
  412.  
  413.         mov     dx, sc_index        ; point the vga sequencer to the map
  414.         mov     al, map_mask        ; mask register, so that we only need
  415.         out     dx, al              ; to send out 1 byte per column.
  416.  
  417.         inc     dx                  ; move to the sequencer's data register.
  418.         and     cx, 3               ; calculate the starting plane. this is
  419.         mov     al, 11h             ; just:
  420.         shl     al, cl              ; plane =  (11h << (x and 3))
  421.         out     dx, al              ; select the first plane.
  422.  
  423.         xor     ecx,ecx
  424.         mov     cx, sourcewidth     ; use cx for source width
  425.         mov     xad, ecx
  426.         shl     sourcewidth,1
  427.  
  428.         align   16                  ; since this point gets jumped to a lot,
  429.                                     ; make sure that it is dword aligned.
  430. rowloop2:
  431.         push    esi                 ; save the starting source index
  432.         push    edi                 ; save the starting dest index
  433.         push    ax                  ; save the current plane mask
  434.         push    bp                  ; save the current base pointer
  435.  
  436.         mov     cx, clippedheight   ; use al for row counter (0-239)
  437.         mov     bx, decisiony       ; use bx for decision variable
  438.         mov     dx, sourceheight    ; use dx for source height * 2
  439.         add     dx, dx
  440.         mov     bp, destheight      ; use bp for dest height * 2
  441.         add     bp, bp
  442.         mov     ah, [esi]           ; get the first source pixel
  443.         or      ah,ah
  444.         jz      s null_loop         ; if zero, perform null loop
  445.  
  446.         align   4                   ; common jump point... align for speed.
  447. columnloop2:
  448.         mov     [edi], ah           ; draw a pixel
  449.         dec     cx                  ; decrement line counter
  450.         jz      s donewithcol2      ; see if we're done with this column
  451.         add     edi, xactual/4      ; go on to the next screen row
  452.         add     bx, dx              ; increment the decision variable
  453.         js      s columnloop2       ; draw this source pixel again
  454.  
  455. incsourcerow2:
  456.         add     esi, xad            ; move to the next source pixel
  457.         sub     bx, bp              ; decrement the decision variable
  458.         jns     s incsourcerow2     ; see if we need to skip another source pixel
  459.         mov     ah, [esi]           ; get the next source pixel
  460.         cmp     ah,0
  461.         jz      s null_loop
  462.         jmp     s columnloop2       ; start drawing this pixel
  463.  
  464. donewithcol2:
  465.         pop     bp                  ; restore bp to access variables
  466.         pop     ax                  ; restore al = plane mask
  467.         pop     edi                 ; restore di to top row of screen
  468.         pop     esi                 ; restore si to top row of source bits
  469.  
  470.         rol     al, 1               ; move to next plane
  471.         adc     edi, 0              ; go on to next screen column
  472.         mov     dx, sc_data         ; tell the vga what column we're in
  473.         out     dx, al              ; by updating the map mask register
  474.  
  475.         mov     bx, decisionx       ; use bx for the x decision variable
  476.         add     bx, sourcewidth     ; increment the x decision variable
  477.         js      s nextcol2          ; jump if we're still in the same source col.
  478.         mov     dx, destwidth       ; dx = w * 2
  479.         add     dx, dx
  480. incsourcecol2:
  481.         inc     esi                 ; move to next source column
  482.         sub     bx, dx              ; decrement x decision variable
  483.         jns     s incsourcecol2     ; see if we skip another source column
  484. nextcol2:
  485.         mov     decisionx, bx       ; free up bx for colloop
  486.         dec     clippedwidth        ; if we're not at last column
  487.         jnz     rowloop2            ;    then do another column
  488. done2:
  489.         ret                         ; we're done!
  490.  
  491.         align   16                  ; common jump point... align for speed.
  492. null_loop:
  493.         dec     cx                  ; decrement line counter
  494.         jz      s donewithcol2      ; see if we're done with this column
  495.         add     edi, xactual/4      ; go on to the next screen row
  496.         add     bx, dx              ; increment the decision variable
  497.         js      s null_loop         ; perform more increments
  498.         jmp     s incsourcerow2
  499.  
  500. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  501. ;
  502. ; Repeat_Bitmap - Draw repeated bit map.
  503. ; In:
  504. ;    REGS = none
  505. ; Stack frame:
  506. ;    DWORD: offset to bitmap
  507. ;     WORD: left   x of window - non-cartisian...
  508. ;     WORD: top    y of window
  509. ;     WORD: right  x of window
  510. ;     WORD: bottom y of window
  511. ; MEMORY:
  512. ; current_page - current offset of video memory for page of xmode, see xmode.asm
  513. ;
  514. ; Out:
  515. ;    null
  516. ;
  517. ; Notes:
  518. ;
  519. ; Good for backgrounds in menus and title  screens.
  520. ; routine is NOT intended for animation because it is slow. uses scale routine
  521. ; because scale routine clips bitmaps.  sloppy routine just draws all over the
  522. ; place and lets the scale clip borders handle the rest.
  523. ;
  524. ; remember: first two words of bitmap define width and height
  525. ;
  526. ; From C (Ug...)
  527. ; repeat_bitmap (seg bitmap, x1%, y1%, x2%, y2%)
  528. ;
  529. ; From assembley (oh, yes)
  530. ;
  531. ; push offset bitmaptorepeat
  532. ; push x1
  533. ; push y1
  534. ; push x2
  535. ; push y2
  536. ; call repeat_bitmap
  537. ;
  538. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  539.  
  540. rb_stack   struc
  541.      rb_wide    dw  ?   ; height and width of bitmap
  542.      rb_height  dw  ?
  543.      rb_curx    dw  ?   ; current bitmap location
  544.      rb_cury    dw  ?
  545.      rb_oldy2   dw  ?   ; old cliping borders save
  546.      rb_oldx2   dw  ?
  547.      rb_oldy1   dw  ?
  548.      rb_oldx1   dw  ?
  549.                 dd  ?x3 ; edi, esi, ebp
  550.                 dd  ?   ; caller
  551.      rb_y2      dw  ?   ; y2
  552.      rb_x2      dw  ?   ; x2
  553.      rb_y1      dw  ?   ; y1
  554.      rb_x1      dw  ?   ; x1
  555.      rb_bitmap  dd  ?   ; offset to bitmap
  556. rb_stack   ends
  557.  
  558. repeat_bitmap:
  559.            push ebp esi edi       ; preserve important registers
  560.            sub esp, 16            ; allocate workspace
  561.            mov ebp, esp           ; set up stack frame
  562.  
  563.            mov ax,cliplt          ; save old borders just in case
  564.            mov [ebp].rb_oldx1,ax
  565.            mov ax,cliprt
  566.            mov [ebp].rb_oldx2,ax
  567.            mov ax,cliptp
  568.            mov [ebp].rb_oldy1,ax
  569.            mov ax,clipbt
  570.            mov [ebp].rb_oldy2,ax
  571.  
  572.            mov x1,4
  573.  
  574.            mov ax,[ebp].rb_x1     ; set new borders for clipping
  575.            mov cliplt,ax
  576.            mov ax,[ebp].rb_x2
  577.            mov cliprt,ax
  578.            mov ax,[ebp].rb_y1
  579.            mov cliptp,ax
  580.            mov ax,[ebp].rb_y2
  581.            mov clipbt,ax
  582.  
  583.            mov [ebp].rb_curx,0    ; we could start at x1,y1 but this
  584.            mov [ebp].rb_cury,0    ; will make offset backgrounds
  585.  
  586.            mov esi,[ebp].rb_bitmap
  587.            mov bitmap,esi
  588.            lodsw                  ; set destination width same as original
  589.            mov [ebp].rb_wide,ax
  590.            lodsw
  591.            mov [ebp].rb_height,ax
  592. nextline:
  593.            mov ax,[ebp].rb_wide
  594.            mov destwidth,ax
  595.            mov ax,[ebp].rb_height
  596.            mov destheight,ax
  597.  
  598.            mov ax,[ebp].rb_curx
  599.            mov destx,ax
  600.            mov ax,[ebp].rb_cury
  601.            mov desty,ax
  602.  
  603.            push ebp
  604.            call xscale2           ; draw a transparent bitmap
  605.            pop ebp
  606.  
  607.            mov ax,[ebp].rb_curx
  608.            add ax,[ebp].rb_wide
  609.            mov [ebp].rb_curx,ax
  610.            cmp ax,[ebp].rb_x2
  611.            jle s nextline
  612.  
  613.            mov [ebp].rb_curx,0
  614.  
  615.            mov ax,[ebp].rb_cury
  616.            add ax,[ebp].rb_height
  617.            mov [ebp].rb_cury,ax
  618.            cmp ax,[ebp].rb_y2
  619.            jle s nextline
  620.  
  621.            mov ax,[ebp].rb_oldx1
  622.            mov cliplt,ax
  623.            mov ax,[ebp].rb_oldx2
  624.            mov cliprt,ax
  625.            mov ax,[ebp].rb_oldy1
  626.            mov cliptp,ax
  627.            mov ax,[ebp].rb_oldy2
  628.            mov clipbt,ax
  629.  
  630.            add esp, 16
  631.            pop edi esi ebp
  632.            ret 12
  633.  
  634. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  635. ;
  636. ; TDraw_Scale4 - Draw transparent scaled bitmap using 1/4 xmode method:
  637. ;                draws every 4th pixel alike.
  638. ; In:
  639. ;    ESI - offset of bitmap to draw, first two words are x,y size
  640. ;     AX - x width to scale to
  641. ;     BX - y width to scale to
  642. ;     CX - x location, non-cartisian
  643. ;     DX - y location, non-cartisian
  644. ; current_page - current offset of video memory for page of xmode, see xmode.asm
  645. ;
  646. ; Out:
  647. ;    null
  648. ;
  649. ; Notes:
  650. ;  great  for  explosions/smoke  where  the  bitmap  does  not have to be  very
  651. ;  accuratly drawn - much faster
  652. ;
  653. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  654.  
  655. done4:  ret
  656.  
  657. tdraw_scale4:
  658.         mov bitmap,esi
  659.         mov destwidth,ax
  660.         mov destheight,bx
  661.         mov destx,cx
  662.         mov desty,dx
  663.  
  664. xscale4:
  665.         cmp     destwidth, 2        ; if destination width is less than 2
  666.         jl      s done4             ;     then don't draw it.
  667.  
  668.         cmp     destheight, 2       ; if destination height is less than 2
  669.         jl      s done4             ;     then don't draw it.
  670.  
  671.         mov     ax, desty           ; if it is completely below the
  672.         cmp     ax, clipbt          ; lower clip bondry,
  673.         jg      s done4             ;     then don't draw it.
  674.  
  675.         add     ax, destheight      ; if it is above clip boundries
  676.         dec     ax                  ;     then don't draw it.
  677.         cmp     ax, cliptp
  678.         jl      s done4
  679.  
  680.         mov     ax, destx           ; if it is to the right of the
  681.         mov     cx, cliprt          ; right clip boundry
  682.         cmp     ax, cliprt          ;     then don't draw it.
  683.         jg      s done4
  684.  
  685.         add     ax, destwidth       ; if it is completely to the left
  686.         dec     ax                  ; of the left clip boundry,
  687.         cmp     ax, cliplt          ;     then don't draw it.
  688.         jl      s done4
  689.  
  690.         mov     esi, bitmap         ; make esi point to bitmap data
  691.         lodsw                       ; get source x width
  692.         mov     sourcewidth,ax
  693.         lodsw                       ; get source y height
  694.         mov     sourceheight,ax
  695.  
  696.         mov     ax, destwidth       ; clippedwidth is initially set to
  697.         mov     clippedwidth, ax    ; the requested dest width.
  698.  
  699.         add     ax,ax               ; initialize the x decision var
  700.         neg     ax                  ; to be -2*destwidth
  701.         mov     decisionx, ax       ;
  702.  
  703.         mov     ax, destheight      ; clippedheight is initially set to
  704.         mov     clippedheight, ax   ; the requested dest size.
  705.  
  706.         add     ax,ax               ; initialize the y decision var
  707.         neg     ax                  ; to be -2*destheight
  708.         mov     decisiony, ax       ;
  709.  
  710.         movsx   eax, cliptp         ; if y is below the top
  711.         mov     edx, eax            ; clipping boundry, then we don't
  712.         sub     dx, desty           ; need to clip the top, so we can
  713.         js      s notopclip4        ; jump over the clipping stuff.
  714.  
  715.         mov     desty, ax           ; this block performs clipping on the
  716.         sub     clippedheight, dx   ; top of the bitmap.  i have heavily
  717.         movsx   ecx, sourceheight   ; optimized this block to use only 4
  718.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  719.         mov     eax, ecx            ; gonna try to explain what it's doing.
  720.         cdq                         ; but i can tell you what results from
  721.         movsx   ebx, destheight     ; this:  the decisiony var is updated
  722.         idiv    ebx                 ; to start at the right clipped row.
  723.         movsx   edx, sourcewidth    ; y is moved to the top clip
  724.         imul    edx, eax            ; boundry. clippedheight is lowered since
  725.         add     esi, edx            ; we won't be drawing all the requested
  726.         imul    eax, ebx            ; rows. esi is changed to point over
  727.         sub     ecx, eax            ; the bitmap data that is clipped off.
  728.         sub     ecx, ebx            ;
  729.         add     ecx, ecx            ;
  730.         mov     decisiony, cx       ; <end of top clipping block >
  731.  
  732. notopclip4:
  733.         mov     ax, desty           ; if the bitmap doesn't extend over the
  734.         add     ax, clippedheight   ; bottom clipping boundry, then we
  735.         dec     ax                  ; don't need to clip the bottom, so we
  736.         cmp     ax, clipbt          ; can jump over the bottom clip code.
  737.         jle     s nobottomclip4
  738.  
  739.         mov     ax, clipbt          ; clip off the bottom by reducing the
  740.         sub     ax, desty           ; clippedheight so that the bitmap won't
  741.         inc     ax                  ; extend over the lower clipping
  742.         mov     clippedheight, ax   ; boundry.
  743.  
  744. nobottomclip4:
  745.         movsx   eax, cliplt         ; if x is to the left of the
  746.         mov     edx, eax            ; top clipping boundry, then we don't
  747.         sub     dx, destx           ; need to clip the left, so we can
  748.         js      s noleftclip4       ; jump over the clipping stuff.
  749.  
  750.         mov     destx, ax           ; this block performs clipping on the
  751.         sub     clippedwidth, dx    ; left of the bitmap.  i have heavily
  752.         movsx   ecx, sourcewidth    ; optimized this block to use only 4
  753.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  754.         mov     eax, ecx            ; gonna try to explain what it's doing.
  755.         cdq                         ; but i can tell you what results from
  756.         movsx   ebx, destwidth      ; this:  the decisionx var is updated
  757.         idiv    ebx                 ; to start at the right clipped column.
  758.         add     esi, eax            ; x is moved to the left clip
  759.         imul    eax, ebx            ; boundry. clippedwidth is reduced since
  760.         sub     ecx, eax            ; we won't be drawing all the requested
  761.         sub     ecx, ebx            ; cols. esi is changed to point over
  762.         add     ecx, ecx            ; the bitmap data that is clipped off.
  763.         mov     decisionx, cx       ; <end of left clipping block >
  764.  
  765. noleftclip4:
  766.         mov     ax, destx           ; if the bitmap doesn't extend over the
  767.         add     ax, clippedwidth    ; right clipping boundry, then we
  768.         dec     ax                  ; don't need to clip the right, so we
  769.         cmp     ax, cliprt          ; can jump over the right clip code.
  770.         jle     s noclipright4
  771.  
  772.         mov     ax, cliprt          ; clip off the right by reducing the
  773.         sub     ax, destx           ; clippedwidth so that the bitmap won't
  774.         inc     ax                  ; extend over the right clipping
  775.         mov     clippedwidth, ax    ; boundry.
  776.  
  777.         ;calculate starting video address
  778. noclipright4:
  779.         movsx   edi, desty          ; we are going to set edi to start point
  780.         imul    edi, xactual/4
  781.         movsx   eax, destx          ; the offset edi is
  782.         mov     cx, ax              ; calculated by:
  783.         shr     eax, 2              ; edi = y*80+x/2
  784.         add     eax, current_page
  785.         add     edi,eax             ; edi is ready!
  786.  
  787.         mov     dx, sc_index        ; point the vga sequencer to the map
  788.         mov     al, map_mask        ; mask register, so that we only need
  789.         out     dx, al              ; to send out 1 byte per column.
  790.  
  791.         inc     dx                  ; move to the sequencer's data register.
  792.         mov     al, all_planes
  793.         out     dx, al              ; select the first plane.
  794.  
  795.         xor     ecx,ecx
  796.         mov     cx, sourcewidth     ; use cx for source width
  797.         mov     xad, ecx
  798.  
  799.         shl     sourcewidth,1+2     ; 4 times as fast
  800.         shr     clippedwidth,2      ; 1/4 of the plots
  801.  
  802.         cmp     clippedwidth,0      ; check if <4 wide
  803.         jne     s rowloop4
  804.         inc     clippedwidth
  805.  
  806.         align   16                  ; since this point gets jumped to a lot,
  807.                                     ; make sure that it is dword aligned.
  808. rowloop4:
  809.         push    esi                 ; save the starting source index
  810.         push    edi                 ; save the starting dest index
  811.         push    bp                  ; save the current base pointer
  812.  
  813.         mov     cx, clippedheight   ; use al for row counter (0-239)
  814.         mov     bx, decisiony       ; use bx for decision variable
  815.         mov     dx, sourceheight    ; use dx for source height * 2
  816.         add     dx, dx
  817.         mov     bp, destheight      ; use bp for dest height * 2
  818.         add     bp, bp
  819.         mov     ah, [esi]           ; get the first source pixel
  820.         or      ah,ah
  821.         jz      s null_loop4        ; if zero, perform null loop
  822.  
  823.         align   4                   ; common jump point... align for speed.
  824. columnloop4:
  825.         mov     [edi], ah           ; draw a pixel
  826.         dec     cx                  ; decrement line counter
  827.         jz      s donewithcol4      ; see if we're done with this column
  828.         add     edi, xactual/4      ; go on to the next screen row
  829.         add     bx, dx              ; increment the decision variable
  830.         js      s columnloop4       ; draw this source pixel again
  831.  
  832. incsourcerow4:
  833.         add     esi, xad            ; move to the next source pixel
  834.         sub     bx, bp              ; decrement the decision variable
  835.         jns     s incsourcerow4     ; see if we need to skip another source pixel
  836.         mov     ah, [esi]           ; get the next source pixel
  837.         or      ah,ah
  838.         jz      s null_loop4
  839.         jmp     s columnloop4       ; start drawing this pixel
  840.  
  841. donewithcol4:
  842.         pop     bp                  ; restore bp to access variables
  843.         pop     edi                 ; restore di to top row of screen
  844.         pop     esi                 ; restore si to top row of source bits
  845.  
  846.         add     edi, 1              ; go on to next screen column
  847.  
  848.         mov     bx, decisionx       ; use bx for the x decision variable
  849.         add     bx, sourcewidth     ; increment the x decision variable
  850.         mov     dx, destwidth       ; dx = w * 2
  851.         add     dx, dx
  852. incsourcecol4:
  853.         inc     esi                 ; move to next source column
  854.         sub     bx, dx              ; decrement x decision variable
  855.         jns     s incsourcecol4     ; see if we skip another source column
  856. nextcol4:
  857.         mov     decisionx, bx       ; free up bx for colloop
  858.         dec     clippedwidth        ; if we're not at last column
  859.         jnz     rowloop4            ;    then do another column
  860.  
  861.         ret                         ; we're done!
  862.  
  863.         align   16                  ; common jump point... align for speed.
  864. null_loop4:
  865.         dec     cx                  ; decrement line counter
  866.         jz      s donewithcol4      ; see if we're done with this column
  867.         add     edi, xactual/4      ; go on to the next screen row
  868.         add     bx, dx              ; increment the decision variable
  869.         js      s null_loop4        ; perform more increments
  870.         jmp     s incsourcerow4
  871.  
  872.